import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import axios from 'axios';

// Types
interface User {
  _id: string;
  username: string;
  email: string;
  firstName?: string;
  lastName?: string;
  role: string;
  profilePicture?: string;
  bio?: string;
  preferences: {
    theme: 'light' | 'dark';
    aiProvider: string;
    notifications: {
      email: boolean;
      push: boolean;
    };
  };
  progress: {
    currentLevel: 'beginner' | 'intermediate' | 'advanced';
    completedPatterns: {
      beginner: string[];
      intermediate: string[];
      advanced: string[];
    };
    currentPattern: string | null;
    achievements: string[];
  };
}

interface AuthState {
  token: string | null;
  isAuthenticated: boolean;
  loading: boolean;
  user: User | null;
  error: string | null;
}

const initialState: AuthState = {
  token: localStorage.getItem('token'),
  isAuthenticated: false,
  loading: true,
  user: null,
  error: null
};

// Load user
export const loadUser = createAsyncThunk('auth/loadUser', async (_, { rejectWithValue }) => {
  try {
    const token = localStorage.getItem('token');
    
    if (!token) {
      return rejectWithValue('No token');
    }
    
    const config = {
      headers: {
        'x-auth-token': token
      }
    };
    
    const res = await axios.get('/api/users/me', config);
    return res.data;
  } catch (err: any) {
    localStorage.removeItem('token');
    return rejectWithValue(err.response?.data?.msg || 'Server Error');
  }
});

// Register user
export const register = createAsyncThunk(
  'auth/register',
  async (userData: { username: string; email: string; password: string; firstName?: string; lastName?: string }, 
    { rejectWithValue }) => {
    try {
      const config = {
        headers: {
          'Content-Type': 'application/json'
        }
      };
      
      const res = await axios.post('/api/users/register', userData, config);
      return res.data;
    } catch (err: any) {
      return rejectWithValue(err.response?.data?.msg || 'Server Error');
    }
  }
);

// Login user
export const login = createAsyncThunk(
  'auth/login',
  async (userData: { email: string; password: string }, { rejectWithValue }) => {
    try {
      const config = {
        headers: {
          'Content-Type': 'application/json'
        }
      };
      
      const res = await axios.post('/api/users/login', userData, config);
      return res.data;
    } catch (err: any) {
      return rejectWithValue(err.response?.data?.msg || 'Server Error');
    }
  }
);

// Update profile
export const updateProfile = createAsyncThunk(
  'auth/updateProfile',
  async (profileData: { firstName?: string; lastName?: string; bio?: string; profilePicture?: string }, 
    { rejectWithValue }) => {
    try {
      const token = localStorage.getItem('token');
      
      if (!token) {
        return rejectWithValue('No token');
      }
      
      const config = {
        headers: {
          'Content-Type': 'application/json',
          'x-auth-token': token
        }
      };
      
      const res = await axios.put('/api/users/profile', profileData, config);
      return res.data;
    } catch (err: any) {
      return rejectWithValue(err.response?.data?.msg || 'Server Error');
    }
  }
);

// Update preferences
export const updatePreferences = createAsyncThunk(
  'auth/updatePreferences',
  async (preferencesData: { theme?: 'light' | 'dark'; aiProvider?: string; notifications?: { email?: boolean; push?: boolean } }, 
    { rejectWithValue }) => {
    try {
      const token = localStorage.getItem('token');
      
      if (!token) {
        return rejectWithValue('No token');
      }
      
      const config = {
        headers: {
          'Content-Type': 'application/json',
          'x-auth-token': token
        }
      };
      
      const res = await axios.put('/api/users/preferences', preferencesData, config);
      return res.data;
    } catch (err: any) {
      return rejectWithValue(err.response?.data?.msg || 'Server Error');
    }
  }
);

const authSlice = createSlice({
  name: 'auth',
  initialState,
  reducers: {
    logout: (state) => {
      localStorage.removeItem('token');
      state.token = null;
      state.isAuthenticated = false;
      state.loading = false;
      state.user = null;
      state.error = null;
    },
    clearError: (state) => {
      state.error = null;
    }
  },
  extraReducers: (builder) => {
    builder
      // Load user
      .addCase(loadUser.pending, (state) => {
        state.loading = true;
      })
      .addCase(loadUser.fulfilled, (state, action: PayloadAction<User>) => {
        state.isAuthenticated = true;
        state.loading = false;
        state.user = action.payload;
      })
      .addCase(loadUser.rejected, (state, action) => {
        state.token = null;
        state.isAuthenticated = false;
        state.loading = false;
        state.user = null;
        state.error = action.payload as string;
      })
      // Register
      .addCase(register.pending, (state) => {
        state.loading = true;
      })
      .addCase(register.fulfilled, (state, action: PayloadAction<{ token: string }>) => {
        localStorage.setItem('token', action.payload.token);
        state.token = action.payload.token;
        state.isAuthenticated = true;
        state.loading = false;
      })
      .addCase(register.rejected, (state, action) => {
        state.token = null;
        state.isAuthenticated = false;
        state.loading = false;
        state.user = null;
        state.error = action.payload as string;
      })
      // Login
      .addCase(login.pending, (state) => {
        state.loading = true;
      })
      .addCase(login.fulfilled, (state, action: PayloadAction<{ token: string }>) => {
        localStorage.setItem('token', action.payload.token);
        state.token = action.payload.token;
        state.isAuthenticated = true;
        state.loading = false;
      })
      .addCase(login.rejected, (state, action) => {
        state.token = null;
        state.isAuthenticated = false;
        state.loading = false;
        state.user = null;
        state.error = action.payload as string;
      })
      // Update profile
      .addCase(updateProfile.pending, (state) => {
        state.loading = true;
      })
      .addCase(updateProfile.fulfilled, (state, action: PayloadAction<User>) => {
        state.loading = false;
        state.user = action.payload;
      })
      .addCase(updateProfile.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string;
      })
      // Update preferences
      .addCase(updatePreferences.pending, (state) => {
        state.loading = true;
      })
      .addCase(updatePreferences.fulfilled, (state, action: PayloadAction<User['preferences']>) => {
        state.loading = false;
        if (state.user) {
          state.user.preferences = action.payload;
        }
      })
      .addCase(updatePreferences.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string;
      });
  }
});

export const { logout, clearError } = authSlice.actions;

export default authSlice.reducer; 